package com.pro.framework.json.util;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import lombok.SneakyThrows;
import org.springframework.core.io.ClassPathResource;
import org.yaml.snakeyaml.Yaml;

import java.io.File;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

public class YamlUtil {
    public static ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
    static {
//        public static final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    @SneakyThrows
    public static <T> T loadAndMergeYaml(String relativePath, Class<T> clazz) {
        return mapper.convertValue(loadAndMergeYaml(relativePath),clazz);
    }

    @SuppressWarnings({"unchecked", "resource"})
    @SneakyThrows
    public static <T> Map<String, Object> loadAndMergeYaml(String relativePath) {
        Path baseDir = Paths.get(System.getProperty("user.dir"));
        Path resourceDir = baseDir
                .resolve(relativePath)
                .normalize();

        if (!Files.exists(resourceDir)) {
            System.err.println("目录不存在: " + resourceDir.toAbsolutePath());
            return Collections.emptyMap();
        }

        Map<String, Object> merged = new LinkedHashMap<>();
        Files.walk(resourceDir)
                .filter(p -> p.toString().endsWith(".yaml") || p.toString().endsWith(".yml"))
                .forEach(p -> mergeMap(merged, readYamlFile(p, Map.class)));

        return merged;
    }

//    @SneakyThrows
//    public static <T> T readYamlClassPath(String path, Class<T> type) {
//        return readYamlFile(Path.of(new ClassPathResource(path).getFile().getAbsolutePath()), type);
//    }
    @SneakyThrows
    public static <T> T readYamlFile(Path path, Class<T> type) {
        try (var fis = new FileInputStream(path.toFile())) {
            return new Yaml().loadAs(fis, type);
        }
    }


    @SuppressWarnings("unchecked")
    private static void mergeMap(Map<String, Object> a, Map<String, Object> b) {
        if (b == null) return;
        for (Map.Entry<String, Object> entry : b.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            if (value instanceof Map && a.get(key) instanceof Map) {
                mergeMap((Map<String, Object>) a.get(key), (Map<String, Object>) value);
            } else {
                a.put(key, value);
            }
        }
    }


}
